﻿using Senparc.CO2NET.Cache;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Kele.Repository
{
    public static class AppCache
    {
        public static readonly IBaseObjectCacheStrategy CacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();

        public static string MERCHANT = "merchant_{0}";


        public static async Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> factory)
        {
            if (string.IsNullOrWhiteSpace(key)) return await factory.Invoke();


            T value = default;
            var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
            if (cacheStrategy.CheckExisted(key))
            {
                try
                {
                    value = await cacheStrategy.GetAsync<T>(key);
                }
                catch
                {
                    // ignored
                }
            }

            if (value != null) return value;

            value = await factory.Invoke();
            if (value != null)
            {
                await cacheStrategy.SetAsync(key, value);
            }

            return value;
        }

        public static async Task RemoveAsync(string[] keys)
        {
            if (keys != null)
            {
                foreach (var key in keys)
                {
                    await RemoveAsync(key);
                }
            }
        }

        public static async Task RemoveAsync(string key)
        {
            var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
            if (cacheStrategy.CheckExisted(key))
            {
                try
                {
                    await cacheStrategy.RemoveFromCacheAsync(key);
                }
                catch
                {
                    // ignored
                }
            }
        }

        public static string GetPathKey(string filePath)
        {
            var text = string.IsNullOrEmpty(filePath) ? string.Empty : filePath.ToLower();
            return $"{text}";
        }

        public static string ToString(IEnumerable<string> objects, string separator = ",")
        {
            return objects != null ? string.Join(separator, objects) : string.Empty;
        }

        public static string ToString(IEnumerable<int> objects, string separator = ",")
        {
            return objects != null ? string.Join(separator, objects) : string.Empty;
        }

        public static string ToString(IEnumerable<object> objects, string separator = ",")
        {
            return objects != null ? string.Join(separator, objects) : string.Empty;
        }

        public static string GetClassKey(Type type, params string[] values)
        {
            if (values == null || values.Length <= 0) return $"{type.FullName}";
            return $"{type.FullName}:{ToString(values, ":")}";
        }

        public static string GetEntityKey(string tableName)
        {
            return $"{tableName}:entity:only";
        }

        public static string GetEntityKey(string tableName, int id)
        {
            return $"{tableName}:entity:{id}";
        }

        public static string GetEntityKey(string tableName, string type, string identity)
        {
            return $"{tableName}:entity:{type}:{identity}";
        }

        public static string GetListKey(string tableName)
        {
            return $"{tableName}:list";
        }

        public static string GetListKey(string tableName, int groupId)
        {
            return $"{tableName}:list:{groupId}";
        }

        public static string GetListKey(string tableName, string type)
        {
            return $"{tableName}:list:{type}";
        }

        public static string GetListKey(string tableName, string type, params string[] identities)
        {
            return $"{tableName}:list:{type}:{ToString(identities, ":")}";
        }

        public static string GetCountKey(string tableName, int siteId)
        {
            return $"{tableName}:count:{siteId}";
        }

        public static string GetCountKey(string tableName, int siteId, int channelId)
        {
            return $"{tableName}:count:{siteId}:{channelId}";
        }

        public static string GetCountKey(string tableName, int siteId, int channelId, int adminId)
        {
            return $"{tableName}:count:{siteId}:{channelId}:{adminId}";
        }

        public static string GetCountKey(string tableName, int siteId, int channelId, params string[] identities)
        {
            return $"{tableName}:count:{siteId}:{channelId}:{ToString(identities, ":")}";
        }
    }
}